#include "VSASYNLoader.h"
#include "VSGraphicInclude.h"
using namespace VSEngine2;
VSResourceJob::VSResourceJob()
{
	m_uiLoadState = LS_PENDING;
	m_uiJobType = JT_TEXTURE;
}
VSResourceJob::~VSResourceJob()
{
	
}
VSTextureRJob::VSTextureRJob(VSTexAllStateRPtr& pProxy)
{
	m_pProxy = pProxy;
	m_pNewResource = NULL;
	m_bEngineType = true;
	m_bCompress = 0;
	m_uiCompressType = 0;
	m_bIsNormal = false;
	m_bIsSoftSRGB = false;
	m_pSamplerState = NULL;
	m_uiJobType = JT_TEXTURE;
}
VSTextureRJob::~VSTextureRJob()
{
	m_pProxy = NULL;
	m_pNewResource = NULL;
}
VSMaterialRJob::VSMaterialRJob(VSMaterialRPtr& pProxy)
{
	m_pProxy = pProxy;
	m_pNewResource = NULL;
	m_uiJobType = JT_MATERIAL;
}
VSMaterialRJob::~VSMaterialRJob()
{
	m_pProxy = NULL;
	m_pNewResource = NULL;
}
VSAnimSetRJob::VSAnimSetRJob(VSAnimSetRPtr& pProxy)
{
	m_pProxy = pProxy;
	m_pNewResource = NULL;
	m_uiJobType = JT_ANIMSET;
}
VSAnimSetRJob::~VSAnimSetRJob()
{
	m_pProxy = NULL;
	m_pNewResource = NULL;
}
VSStaticMeshRJob::VSStaticMeshRJob(VSStaticMeshNodeRPtr& pProxy)
{
	m_pProxy = pProxy;
	m_pNewResource = NULL;
	m_uiJobType = JT_STATIC_MESH;
}
VSStaticMeshRJob::~VSStaticMeshRJob()
{
	m_pProxy = NULL;
	m_pNewResource = NULL;
}
VSSkelectonMeshRJob::VSSkelectonMeshRJob(VSSkelectonMeshNodeRPtr& pProxy)
{
	m_pProxy = pProxy;
	m_pNewResource = NULL;
	m_uiJobType = JT_SKELECTON_MESH;
}
VSSkelectonMeshRJob::~VSSkelectonMeshRJob()
{
	m_pProxy = NULL;
	m_pNewResource = NULL;
}
VSVShaderRJob::~VSVShaderRJob()
{
	m_pProxy = NULL;
	m_pNewResource = NULL;
}
VSVShaderRJob::VSVShaderRJob(VSVShaderRPtr& pProxy)
{
	m_pProxy = pProxy;
	m_pNewResource = NULL;
	m_uiJobType = JT_VSHADER;
}
VSPShaderRJob::~VSPShaderRJob()
{
	m_pProxy = NULL;
	m_pNewResource = NULL;
}
VSPShaderRJob::VSPShaderRJob(VSPShaderRPtr& pProxy)
{
	m_pProxy = pProxy;
	m_pNewResource = NULL;
	m_uiJobType = JT_PSHADER;
}
void VSResourceLoaderThread::Stop()
{
	
	VSThread::Stop();
	
}
VSResourceLoaderThread::VSResourceLoaderThread()
{
	m_pResourceQueue.Clear();
}
VSResourceLoaderThread::~VSResourceLoaderThread()
{
	m_pResourceQueue.Clear();
}
void VSResourceLoaderThread::AddJob(VSResourceJob* m_pJob)
{
	bool IsEmpty = m_pResourceQueue.IsEmpty();
	m_pResourceQueue.Enqueue(m_pJob);

}

void VSResourceLoaderThread::Run()
{
	while(!IsStopTrigger())
	{
		while(!m_pResourceQueue.IsEmpty())
		{
			VSResourceJob* pJob = NULL;
			m_pResourceQueue.Dequeue(pJob);

			if (pJob->m_uiJobType == VSResourceJob::JT_TEXTURE)
			{
				LoadTexture((VSTextureRJob *)pJob);
			}
			else if (pJob->m_uiJobType == VSResourceJob::JT_MATERIAL)
			{
				LoadMaterial((VSMaterialRJob *)pJob);
			}	
			else if (pJob->m_uiJobType == VSResourceJob::JT_ANIMSET)
			{
				LoadAnimSet((VSAnimSetRJob *)pJob);
			}
			else if (pJob->m_uiJobType == VSResourceJob::JT_STATIC_MESH)
			{
				LoadStaticMesh((VSStaticMeshRJob *)pJob);
			}
			else if (pJob->m_uiJobType == VSResourceJob::JT_SKELECTON_MESH)
			{
				LoadSkelectonMesh((VSSkelectonMeshRJob *)pJob);
			}
			else if (pJob->m_uiJobType == VSResourceJob::JT_VSHADER)
			{
				LoadVShader((VSVShaderRJob *)pJob);
			}
			else if (pJob->m_uiJobType == VSResourceJob::JT_PSHADER)
			{
				LoadPShader((VSPShaderRJob *)pJob);
			}
		}
	}

}
void VSResourceLoaderThread::LoadMaterial(VSMaterialRJob * pMaterialRJob)
{
	VSMaterialR * pResourceProxy = pMaterialRJob->m_pProxy;
	pMaterialRJob->m_pNewResource = VSResourceManager::LoadMaterial(pMaterialRJob->m_FileName.GetBuffer());
	
	if (!pMaterialRJob->m_pNewResource)
	{
		pMaterialRJob->m_uiLoadState = VSResourceJob::LS_FAIL;
	}
	else
	{
		pMaterialRJob->m_pNewResource->SetResourceName(pResourceProxy->GetResourceName());
		pMaterialRJob->m_uiLoadState = VSResourceJob::LS_LOADED;
	}
}
void VSResourceLoaderThread::LoadStaticMesh(VSStaticMeshRJob * pStaicMeshRJob)
{
	VSStaticMeshNodeR * pResourceProxy = pStaicMeshRJob->m_pProxy;
	pStaicMeshRJob->m_pNewResource = VSResourceManager::LoadStaticMesh(pStaicMeshRJob->m_FileName.GetBuffer());
	if (!pStaicMeshRJob->m_pNewResource)
	{
		pStaicMeshRJob->m_uiLoadState = VSResourceJob::LS_FAIL;
	}
	else
	{
		pStaicMeshRJob->m_pNewResource->SetResourceName(pResourceProxy->GetResourceName());
		pStaicMeshRJob->m_uiLoadState = VSResourceJob::LS_LOADED;
	}
}
void VSResourceLoaderThread::LoadSkelectonMesh(VSSkelectonMeshRJob * pSkelectonMeshRJob)
{
	VSSkelectonMeshNodeR * pResourceProxy = pSkelectonMeshRJob->m_pProxy;
	pSkelectonMeshRJob->m_pNewResource = VSResourceManager::LoadSkelectonMesh(pSkelectonMeshRJob->m_FileName.GetBuffer());
	if (!pSkelectonMeshRJob->m_pNewResource)
	{
		pSkelectonMeshRJob->m_uiLoadState = VSResourceJob::LS_FAIL;
	}
	else
	{
		pSkelectonMeshRJob->m_pNewResource->SetResourceName(pResourceProxy->GetResourceName());
		pSkelectonMeshRJob->m_uiLoadState = VSResourceJob::LS_LOADED;
	}
}
void VSResourceLoaderThread::LoadAnimSet(VSAnimSetRJob * pAnimSetRJob)
{
	VSAnimSetR * pResourceProxy = pAnimSetRJob->m_pProxy;
	pAnimSetRJob->m_pNewResource = VSResourceManager::LoadAnimSet(pAnimSetRJob->m_FileName.GetBuffer());
	if (!pAnimSetRJob->m_pNewResource)
	{
		pAnimSetRJob->m_uiLoadState = VSResourceJob::LS_FAIL;
	}
	else
	{
		pAnimSetRJob->m_pNewResource->SetResourceName(pResourceProxy->GetResourceName());
		pAnimSetRJob->m_uiLoadState = VSResourceJob::LS_LOADED;
	}
}
void VSResourceLoaderThread::LoadVShader(VSVShaderRJob * pVShaderRJob)
{
	VSVShaderR * pResourceProxy = pVShaderRJob->m_pProxy;
	pVShaderRJob->m_pNewResource = VSResourceManager::CreateVShader(pVShaderRJob->m_Para,pVShaderRJob->uiPassType,pVShaderRJob->uiShaderID);
	if (!pVShaderRJob->m_pNewResource)
	{
		pVShaderRJob->m_uiLoadState = VSResourceJob::LS_FAIL;
	}
	else
	{
		pVShaderRJob->m_uiLoadState = VSResourceJob::LS_LOADED;
	}
}
void VSResourceLoaderThread::LoadPShader(VSPShaderRJob * pPShaderRJob)
{
	VSPShaderR * pResourceProxy = pPShaderRJob->m_pProxy;
	pPShaderRJob->m_pNewResource = VSResourceManager::CreatePShader(pPShaderRJob->m_Para,pPShaderRJob->uiPassType,pPShaderRJob->uiShaderID);
	if (!pPShaderRJob->m_pNewResource)
	{
		pPShaderRJob->m_uiLoadState = VSResourceJob::LS_FAIL;
	}
	else
	{
		pPShaderRJob->m_uiLoadState = VSResourceJob::LS_LOADED;
	}
}
void VSResourceLoaderThread::LoadTexture(VSTextureRJob * pTextureRJob)
{
	VSTexAllStateR * pResourceProxy = pTextureRJob->m_pProxy;
	VSUsedName ResourceName = pResourceProxy->GetResourceName();
	if (pTextureRJob->m_bEngineType)
	{
#ifdef NEW_IO
	pTextureRJob->m_pNewResource = VSResourceManager::NewLoadTexture(pTextureRJob->m_FileName.GetBuffer());
#else
	pTextureRJob->m_pNewResource = VSResourceManager::LoadTexture(pTextureRJob->m_FileName.GetBuffer());
#endif
		
	}
	else
	{
		if (pTextureRJob->m_bCompress)
		{
			pTextureRJob->m_pNewResource = VSResourceManager::Load2DTextureCompress(pTextureRJob->m_FileName.GetBuffer(),
				pTextureRJob->m_pSamplerState,
				pTextureRJob->m_uiCompressType,
				pTextureRJob->m_bIsNormal,
				pTextureRJob->m_bIsSoftSRGB);
		}
		else
		{
			pTextureRJob->m_pNewResource = VSResourceManager::Load2DTexture(pTextureRJob->m_FileName.GetBuffer(),pTextureRJob->m_pSamplerState);
		}
	}
	if (!pTextureRJob->m_pNewResource)
	{
		pTextureRJob->m_uiLoadState = VSResourceJob::LS_FAIL;
	}
	else
	{
		pTextureRJob->m_pNewResource->SetResourceName(pResourceProxy->GetResourceName());
		pTextureRJob->m_uiLoadState = VSResourceJob::LS_LOADED;
	}
}

VSASYNLoadManager *VSASYNLoadManager::ms_pASYNLoadManager = NULL;
VSASYNLoadManager::VSASYNLoadManager()
{
	
	m_ResourceJobArray.Clear();
	VSMAC_ASSERT(!ms_pASYNLoadManager);
	ms_pASYNLoadManager = this;
}
VSASYNLoadManager::~VSASYNLoadManager()
{

	m_ResourceLoadThread.Start();

	
	m_ResourceLoadThread.Stop();
	
	for (unsigned int i = 0 ; i < m_ResourceJobArray.GetNum() ;i++)
	{
		VSMAC_DELETE(m_ResourceJobArray[i]);
	}
	m_ResourceJobArray.Clear();
}
void VSASYNLoadManager::Update(double AppTime)
{

	unsigned int i = 0 ;
	while(i < m_ResourceJobArray.GetNum())
	{
		if (m_ResourceJobArray[i]->m_uiLoadState == VSResourceJob::LS_PENDING)
		{
			i++;
			continue;
		}
		else if (m_ResourceJobArray[i]->m_uiLoadState == VSResourceJob::LS_LOADED)
		{	
			VSMAC_ASSERT(VSRenderer::ms_pRenderer);
			if (m_ResourceJobArray[i]->m_uiJobType == VSResourceJob::JT_TEXTURE)
			{
				ProcessTexture((VSTextureRJob *)m_ResourceJobArray[i]);
			}
			else if (m_ResourceJobArray[i]->m_uiJobType == VSResourceJob::JT_MATERIAL)
			{
				ProcessMaterial((VSMaterialRJob *)m_ResourceJobArray[i]);
			}
			else if (m_ResourceJobArray[i]->m_uiJobType == VSResourceJob::JT_ANIMSET)
			{
				ProcessAnimSet((VSAnimSetRJob *)m_ResourceJobArray[i]);
			}
			else if (m_ResourceJobArray[i]->m_uiJobType == VSResourceJob::JT_STATIC_MESH)
			{
				ProcessStaticMesh((VSStaticMeshRJob *)m_ResourceJobArray[i]);
			}
			else if (m_ResourceJobArray[i]->m_uiJobType == VSResourceJob::JT_SKELECTON_MESH)
			{
				ProcessSkelectonMesh((VSSkelectonMeshRJob *)m_ResourceJobArray[i]);
			}
			else if (m_ResourceJobArray[i]->m_uiJobType == VSResourceJob::JT_VSHADER)
			{
				ProcessVShader((VSVShaderRJob *)m_ResourceJobArray[i]);
			}
			else if (m_ResourceJobArray[i]->m_uiJobType == VSResourceJob::JT_PSHADER)
			{
				ProcessPShader((VSPShaderRJob *)m_ResourceJobArray[i]);
			}
			VSMAC_DELETE(m_ResourceJobArray[i]);
			m_ResourceJobArray.Erase(i);
			//todo if the load time is too long ,return and next frame to load
		}
		else
		{
			VSMAC_DELETE(m_ResourceJobArray[i]);
			m_ResourceJobArray.Erase(i);
			VSMAC_ASSERT(0);
		}
	}
	if (m_ResourceJobArray.GetNum() == 0)
	{
		m_ResourceLoadThread.Suspend();
	}
}
void VSASYNLoadManager::ProcessTexture(VSTextureRJob * pTextureRJob)
{
	VSTexAllState * pTex = pTextureRJob->m_pNewResource;
	VSRenderer::ms_pRenderer->LoadTexture(pTex->m_pTex);
	pTextureRJob->m_pProxy->SetNewResource(pTex);
	pTextureRJob->m_pProxy->Loaded();
}
void VSASYNLoadManager::ProcessMaterial(VSMaterialRJob * pMaterialRJob)
{
	VSMaterial * pMaterial = pMaterialRJob->m_pNewResource;
	pMaterialRJob->m_pProxy->SetNewResource(pMaterial);
	pMaterialRJob->m_pProxy->Loaded();
}
void VSASYNLoadManager::ProcessAnimSet(VSAnimSetRJob * pAnimSetRJob)
{
	VSAnimSet * pAnimSet = pAnimSetRJob->m_pNewResource;
	pAnimSetRJob->m_pProxy->SetNewResource(pAnimSet);
	pAnimSetRJob->m_pProxy->Loaded();
}
void VSASYNLoadManager::ProcessStaticMesh(VSStaticMeshRJob * pStaticMeshRJob)
{
	VSStaticMeshNode * pStaticMesh = pStaticMeshRJob->m_pNewResource;
	pStaticMeshRJob->m_pProxy->SetNewResource(pStaticMesh);
	pStaticMeshRJob->m_pProxy->Loaded();
}
void VSASYNLoadManager::ProcessSkelectonMesh(VSSkelectonMeshRJob * pSkelectonMeshRJob)
{
	VSSkelectonMeshNode * pSkelectonMesh = pSkelectonMeshRJob->m_pNewResource;
	pSkelectonMeshRJob->m_pProxy->SetNewResource(pSkelectonMesh);
	pSkelectonMeshRJob->m_pProxy->Loaded();
}
void VSASYNLoadManager::ProcessVShader(VSVShaderRJob * pVShaderRJob)
{
	VSVShader * pVShader = pVShaderRJob->m_pNewResource;
	pVShaderRJob->m_pProxy->SetNewResource(pVShader);
	pVShaderRJob->m_pProxy->Loaded();
}
void VSASYNLoadManager::ProcessPShader(VSPShaderRJob * pPShaderRJob)
{
	VSPShader * pPShader = pPShaderRJob->m_pNewResource;
	pPShaderRJob->m_pProxy->SetNewResource(pPShader);
	pPShaderRJob->m_pProxy->Loaded();
}
void VSASYNLoadManager::AddTextureLoad(VSTexAllStateRPtr& pTexture,
									   VSFileName & FileName,
									   bool bEngineType,
									   VSSamplerStatePtr pSamplerState,					
									   bool bCompress,
									   unsigned int uiCompressType,
									   bool bIsNormal ,
									   bool bIsSoftSRGB)
{
	VSTextureRJob* pResourceProxyJob = VS_NEW VSTextureRJob(pTexture);
	pResourceProxyJob->m_bIsNormal = bIsNormal;
	pResourceProxyJob->m_bEngineType = bEngineType;
	pResourceProxyJob->m_pSamplerState = pSamplerState;
	pResourceProxyJob->m_bCompress = bCompress;
	pResourceProxyJob->m_uiCompressType = uiCompressType;
	pResourceProxyJob->m_bIsSoftSRGB = bIsSoftSRGB;
	pResourceProxyJob->m_FileName = FileName;
	m_ResourceJobArray.AddElement(pResourceProxyJob);
	m_ResourceLoadThread.AddJob(pResourceProxyJob);
	
	if (m_ResourceJobArray.GetNum() == 1)
	{
		m_ResourceLoadThread.Start();
	}
}
void VSASYNLoadManager::AddMaterial(VSMaterialRPtr& pMaterial,VSFileName & FileName)
{
	VSMaterialRJob* pResourceProxyJob = VS_NEW VSMaterialRJob(pMaterial);
	pResourceProxyJob->m_FileName = FileName;
	m_ResourceJobArray.AddElement(pResourceProxyJob);
	m_ResourceLoadThread.AddJob(pResourceProxyJob);

	if (m_ResourceJobArray.GetNum() == 1)
	{
		m_ResourceLoadThread.Start();
	}
}
void VSASYNLoadManager::AddAnimSet(VSAnimSetRPtr& pAnimSet,VSFileName & FileName)
{
	VSAnimSetRJob* pResourceProxyJob = VS_NEW VSAnimSetRJob(pAnimSet);
	pResourceProxyJob->m_FileName = FileName;
	m_ResourceJobArray.AddElement(pResourceProxyJob);
	m_ResourceLoadThread.AddJob(pResourceProxyJob);

	if (m_ResourceJobArray.GetNum() == 1)
	{
		m_ResourceLoadThread.Start();
	}
}
void VSASYNLoadManager::AddStaticMesh(VSStaticMeshNodeRPtr& pStaticMesh,VSFileName & FileName)
{
	VSStaticMeshRJob * pResourceProxyJob = VS_NEW VSStaticMeshRJob(pStaticMesh);
	pResourceProxyJob->m_FileName = FileName;
	m_ResourceJobArray.AddElement(pResourceProxyJob);
	m_ResourceLoadThread.AddJob(pResourceProxyJob);

	if (m_ResourceJobArray.GetNum() == 1)
	{
		m_ResourceLoadThread.Start();
	}
}
void VSASYNLoadManager::AddSkelectonMesh(VSSkelectonMeshNodeRPtr& pSkelectonMesh,VSFileName & FileName)
{
	VSSkelectonMeshRJob* pResourceProxyJob = VS_NEW VSSkelectonMeshRJob(pSkelectonMesh);
	pResourceProxyJob->m_FileName = FileName;
	m_ResourceJobArray.AddElement(pResourceProxyJob);
	m_ResourceLoadThread.AddJob(pResourceProxyJob);

	if (m_ResourceJobArray.GetNum() == 1)
	{
		m_ResourceLoadThread.Start();
	}
}
void VSASYNLoadManager::AddVShader(VSVShaderRPtr& pVShader,MaterialShaderPara1 &MSPara1,unsigned int uiPassType,unsigned int uiShaderID)
{
	VSVShaderRJob * pResourceProxyJob = VS_NEW VSVShaderRJob(pVShader);
	pResourceProxyJob->m_Para = MSPara1;
	pResourceProxyJob->uiPassType = uiPassType;
	pResourceProxyJob->uiShaderID = uiShaderID;
	m_ResourceJobArray.AddElement(pResourceProxyJob);
	m_ResourceLoadThread.AddJob(pResourceProxyJob);

	if (m_ResourceJobArray.GetNum() == 1)
	{
		m_ResourceLoadThread.Start();
	}
}
void VSASYNLoadManager::AddPShader(VSPShaderRPtr& pPShader,MaterialShaderPara1 &MSPara1,unsigned int uiPassType,unsigned int uiShaderID)
{
	VSPShaderRJob * pResourceProxyJob = VS_NEW VSPShaderRJob(pPShader);
	pResourceProxyJob->m_Para = MSPara1;
	pResourceProxyJob->uiPassType = uiPassType;
	pResourceProxyJob->uiShaderID = uiShaderID;
	m_ResourceJobArray.AddElement(pResourceProxyJob);
	m_ResourceLoadThread.AddJob(pResourceProxyJob);

	if (m_ResourceJobArray.GetNum() == 1)
	{
		m_ResourceLoadThread.Start();
	}
}